package JavaEE.ManyThread4;
import java.util.*;
public class Demo2 {
    // 形成死锁的四个必要条件:
    // 1.锁是互斥的:同一时间只能有一个线程持有该锁,其他线程必须等待锁释放后才能获取 (如synchronized)
    // (某些特定情况下,可能表现出非互斥性,如:"可重入性"(同一线程可多次获取同一把锁),"读写锁"(只有写互斥))
    // 2.锁不可被抢占:锁被线程1持有时,线程2要拿锁,应该进入"阻塞状态",而非"把锁抢走"
    // 3.请求和保持:拿到锁1时,不去释放锁1,然后尝试拿锁2
    // 4.循环等待:每个线程都在等待一方解锁,构成循环
    public static Object locker1 = new Object();
    public static Object locker2 = new Object();
    // 通过打破3,解决死锁:线程要拿另一把锁时,先释放手里的锁(Demo1中有演示)
    // 通过打破4,解决死锁:加多个锁到时候,按照一定的顺序来加锁
    public static void main(String[] args) throws InterruptedException{
        // t1和t2都按照:先拿locker1,再拿locker2的顺序进行加锁
        // 就不会造成"循环等待"
        Thread t1 = new Thread(() -> {
            synchronized (locker1) {
                try {
                    System.out.println("t1拿到locker1");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (locker2){
                    System.out.println("t1拿到locker2");
                }
            }
        });
        Thread t2 = new Thread(() -> {
            // 如果t2先尝试获取locker2,再locker1,则会造成死锁
            synchronized (locker1){
                try{
                    System.out.println("t2拿到了locker1");
                    Thread.sleep(1000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
                synchronized (locker2){
                    System.out.println("t2拿到了locker2");
                }
            }
        });
        t1.start();
        t2.start();
    }
}
